home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-19 / iritsm3s.zip / BZR2POLY.C < prev    next >
C/C++ Source or Header  |  1991-09-26  |  8KB  |  224 lines

  1. /******************************************************************************
  2. * Bzr2Poly.c - Bezier to polygon/polylines conversion routines.              *
  3. *******************************************************************************
  4. * Written by Gershon Elber, Mar. 90.                          *
  5. ******************************************************************************/
  6.  
  7. #include "cagd_loc.h"
  8.  
  9. /*****************************************************************************
  10. * Routine to convert a single bezier surface to set of triangles         *
  11. * approximating it. FineNess is a finess control on result and the bigger it *
  12. * is more triangles may result. a value of 10 is a good start value.         *
  13. * NULL is returned in case of an error, otherwise list of CagdPolygonStruct. *
  14. *****************************************************************************/
  15. CagdPolygonStruct *BzrSrf2Polygons(CagdSrfStruct *Srf, int FineNess,
  16.              CagdBType ComputeNormals, CagdBType FourPerFlat)
  17. {
  18.     int i, j, FineNessU1, FineNessV1, FineNessU, FineNessV, BaseIndex;
  19.     CagdRType *Pt;
  20.     CagdPointType
  21.     PType = Srf -> PType;
  22.     CagdPtStruct PtCenter, *Pt1, *Pt2, *Pt3, *Pt4, *PtMesh, *PtMeshPtr;
  23.     CagdVecStruct NlCenter, *Nl1, *Nl2, *Nl3, *Nl4, *PtNrml, *PtNrmlPtr;
  24.     CagdPolygonStruct *Poly,
  25.     *PolyHead = NULL;
  26.  
  27.     if (!CAGD_IS_BEZIER_SRF(Srf)) return NULL;
  28.  
  29.     /* Simple heuristic to estimate how many samples to compute. */
  30.     FineNessU = Srf -> UOrder * FineNess / 10;
  31.     FineNessV = Srf -> VOrder * FineNess / 10;
  32.  
  33.     if (FineNessU < 2) FineNessU = 2;
  34.     if (FineNessV < 2) FineNessV = 2;
  35.  
  36.     switch (_CagdLin2Poly) {
  37.     case CAGD_REG_POLY_PER_LIN:
  38.         break;
  39.         case CAGD_ONE_POLY_PER_LIN:
  40.         if (Srf -> UOrder == 2) FineNessU = 2;
  41.         if (Srf -> VOrder == 2) FineNessV = 2;
  42.         break;
  43.         case CAGD_ONE_POLY_PER_COLIN:
  44.         break;
  45.     }
  46.  
  47.     FineNessU1 = FineNessU - 1;
  48.     FineNessV1 = FineNessV - 1;
  49.  
  50.     /* Allocate a mesh to hold all vertices so common vertices need not be   */
  51.     /* Evaluated twice, and evaluate the surface at these mesh points.         */
  52.     PtMeshPtr = PtMesh = (CagdPtStruct *) CagdMalloc(FineNessU * FineNessV *
  53.                             sizeof(CagdPtStruct));
  54.  
  55.     for (i = 0; i < FineNessU; i++)
  56.     for (j = 0; j < FineNessV; j++) {
  57.         Pt = BzrSrfEvalAtParam(Srf, ((CagdRType) i) / FineNessU1,
  58.                         ((CagdRType) j) / FineNessV1);
  59.         CagdCoerceToE3(PtMeshPtr -> Pt, &Pt, -1, PType);
  60.         PtMeshPtr++;
  61.     }
  62.  
  63.     if (ComputeNormals) {
  64.     PtNrmlPtr = PtNrml = (CagdVecStruct *) CagdMalloc(FineNessU * FineNessV *
  65.                               sizeof(CagdVecStruct));
  66.     for (i = 0; i < FineNessU; i++)
  67.         for (j = 0; j < FineNessV; j++) {
  68.         Nl1 = BzrSrfNormal(Srf, ((CagdRType) i) / FineNessU1,
  69.                     ((CagdRType) j) / FineNessV1);
  70.         CAGD_COPY_VECTOR(*PtNrmlPtr, *Nl1);
  71.         PtNrmlPtr++;
  72.         }
  73.     }
  74.  
  75.     /* Now that we have the mesh, create the polygons. */
  76.     for (i = 0; i < FineNessU1; i++)
  77.     for (j = 0; j < FineNessV1; j++) {
  78.         BaseIndex = i * FineNessV + j;
  79.         Pt1 = &PtMesh[BaseIndex];        /* Cache the four flat corners. */
  80.         Pt2 = &PtMesh[BaseIndex + 1];
  81.         Pt3 = &PtMesh[BaseIndex + FineNessV + 1];
  82.         Pt4 = &PtMesh[BaseIndex + FineNessV];
  83.         if (ComputeNormals) {
  84.         Nl1 = &PtNrml[BaseIndex];
  85.         Nl2 = &PtNrml[BaseIndex + 1];
  86.         Nl3 = &PtNrml[BaseIndex + FineNessV + 1];
  87.         Nl4 = &PtNrml[BaseIndex + FineNessV];
  88.         }
  89.  
  90.         if (FourPerFlat) {  /* Eval middle point and create 4 triangles. */
  91.         Pt = BzrSrfEvalAtParam(Srf, (i + 0.5) / FineNessU1,
  92.                             (j + 0.5) / FineNessV1);
  93.         CagdCoerceToE3(PtCenter.Pt, &Pt, -1, PType);
  94.         if (ComputeNormals) {
  95.             /* Average the four normals to find the middle one. */
  96.             CAGD_COPY_VECTOR(NlCenter, *Nl1);
  97.             CAGD_ADD_VECTOR(NlCenter, *Nl2);
  98.             CAGD_ADD_VECTOR(NlCenter, *Nl3);
  99.             CAGD_ADD_VECTOR(NlCenter, *Nl4);
  100.             CAGD_NORMALIZE_VECTOR(NlCenter);
  101.         }
  102.  
  103.         Poly = _CagdMakePolygon(ComputeNormals, Pt1, Pt2, &PtCenter,
  104.                             Nl1, Nl2, &NlCenter);
  105.         CAGD_LIST_PUSH(Poly, PolyHead);
  106.         Poly = _CagdMakePolygon(ComputeNormals, Pt2, Pt3, &PtCenter,
  107.                                 Nl2, Nl3, &NlCenter);
  108.         CAGD_LIST_PUSH(Poly, PolyHead);
  109.         Poly = _CagdMakePolygon(ComputeNormals, Pt3, Pt4, &PtCenter,
  110.                                 Nl3, Nl4, &NlCenter);
  111.         CAGD_LIST_PUSH(Poly, PolyHead);
  112.         Poly = _CagdMakePolygon(ComputeNormals, Pt4, Pt1, &PtCenter,
  113.                                 Nl4, Nl1, &NlCenter);
  114.         CAGD_LIST_PUSH(Poly, PolyHead);
  115.         }
  116.         else {               /* Only two along the diagonal... */
  117.         Poly = _CagdMakePolygon(ComputeNormals, Pt1, Pt2, Pt3,
  118.                                 Nl1, Nl2, Nl3);
  119.         CAGD_LIST_PUSH(Poly, PolyHead);
  120.         Poly = _CagdMakePolygon(ComputeNormals, Pt3, Pt4, Pt1,
  121.                                 Nl3, Nl4, Nl1);
  122.         CAGD_LIST_PUSH(Poly, PolyHead);
  123.         }
  124.     }
  125.  
  126.     CagdFree((VoidPtr) PtMesh);
  127.     if (ComputeNormals) CagdFree((VoidPtr) PtNrml);
  128.  
  129.     return PolyHead;
  130. }
  131.  
  132. /*****************************************************************************
  133. * Routine to convert a single bezier surface to NumOfIsolines polylines list *
  134. * in each param. direction with SamplesPerCurve in each isoparametric curve. *
  135. * Polyline are always E3 of CagdPolylineStruct type.                 *
  136. * Iso parametric curves are sampled equally spaced in parametric space.         *
  137. * NULL is returned in case of an error, otherwise list of CagdPolylineStruct.*
  138. *****************************************************************************/
  139. CagdPolylineStruct *BzrSrf2Polylines(CagdSrfStruct *Srf, int NumOfIsocurves,
  140.                              int SamplesPerCurve)
  141. {
  142.     int i;
  143.     CagdRType t;
  144.     CagdCrvStruct *Crv;
  145.     CagdPolylineStruct *PolyList = NULL, *Poly;
  146.  
  147.     if (!CAGD_IS_BEZIER_SRF(Srf)) return NULL;
  148.  
  149.     /* Make sure requested format is something reasonable. */
  150.     if (SamplesPerCurve < 1) SamplesPerCurve = 1;
  151.     if (SamplesPerCurve > CAGD_MAX_BEZIER_CACHE_ORDER)
  152.     SamplesPerCurve = CAGD_MAX_BEZIER_CACHE_ORDER;
  153.     if (NumOfIsocurves < 2) NumOfIsocurves = 2;
  154.  
  155.     for (i = 0; i < NumOfIsocurves; i++) {
  156.     t = ((CagdRType) i) / (NumOfIsocurves - 1);
  157.     if (t > 1.0) t = 1.0;                 /* In case of round off error. */
  158.  
  159.     Crv = BzrSrfCrvFromSrf(Srf, t, CAGD_CONST_U_DIR);
  160.     Poly = BzrCrv2Polyline(Crv, SamplesPerCurve);
  161.     Poly -> Pnext = PolyList;
  162.     PolyList = Poly;
  163.     CagdCrvFree(Crv);
  164.  
  165.     Crv = BzrSrfCrvFromSrf(Srf, t, CAGD_CONST_V_DIR);
  166.     Poly = BzrCrv2Polyline(Crv, SamplesPerCurve);
  167.     Poly -> Pnext = PolyList;
  168.     PolyList = Poly;
  169.     CagdCrvFree(Crv);
  170.     }
  171.  
  172.     return PolyList;
  173. }
  174.  
  175. /*****************************************************************************
  176. * Routine to convert a single bezier curve to polyline with SamplesPerCurve  *
  177. * samples. Polyline is always E3 of CagdPolylineStruct type.             *
  178. * Curve is sampled equally spaced in parametric space.                 *
  179. * NULL is returned in case of an error, otherwise CagdPolylineStruct.         *
  180. *****************************************************************************/
  181. CagdPolylineStruct *BzrCrv2Polyline(CagdCrvStruct *Crv, int SamplesPerCurve)
  182. {
  183.     int i, j,
  184.     n = 1 << SamplesPerCurve,
  185.     IsNotRational = !CAGD_IS_RATIONAL_CRV(Crv),
  186.     MaxCoord = CAGD_NUM_OF_PT_COORD(Crv -> PType);
  187.     CagdRType *Polyline[CAGD_MAX_PT_SIZE], Scaler;
  188.     CagdPtStruct *NewPolyline;
  189.     CagdPolylineStruct *P;
  190.  
  191.     if (!CAGD_IS_BEZIER_CRV(Crv)) return NULL;
  192.  
  193.     /* Make sure requested format is something reasonable. */
  194.     if (SamplesPerCurve < 1) SamplesPerCurve = 1;
  195.     if (SamplesPerCurve > CAGD_MAX_BEZIER_CACHE_ORDER)
  196.     SamplesPerCurve = CAGD_MAX_BEZIER_CACHE_ORDER;
  197.  
  198.     P = CagdPolylineNew(n);
  199.     NewPolyline = P -> Polyline;
  200.  
  201.     /* Allocate temporary memory to hold evaluated curve. */
  202.     for (i = 0; i < CAGD_MAX_PT_SIZE; i++)
  203.     Polyline[i] = (CagdRType *) CagdMalloc(sizeof(CagdRType) * n);
  204.  
  205.     if (MaxCoord > 3) MaxCoord = 3;
  206.  
  207.     BzrCrvEvalToPolyline(Crv, SamplesPerCurve, Polyline);
  208.  
  209.     for (i = n - 1; i >= 0; i--) {              /* Convert to E3 polyline. */
  210.     if (IsNotRational)
  211.         Scaler = 1.0;
  212.     else
  213.         Scaler = Polyline[0][i];
  214.  
  215.     for (j = 0; j < MaxCoord; j++)
  216.        NewPolyline[i].Pt[j] = Polyline[j+1][i] / Scaler;
  217.     for (j = MaxCoord; j < 3; j++)
  218.        NewPolyline[i].Pt[j] = 0.0;
  219.     }
  220.     for (i = 0; i < CAGD_MAX_PT_SIZE; i++) CagdFree((VoidPtr) Polyline[i]);
  221.  
  222.     return P;
  223. }
  224.